﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using Devsoft.Net.HttpClient;
using Moq;
using Devsoft.Utilities.Extentions;

namespace Devsoft.NUnit.Common
{
    public static class HttpClientMock
    {

        public static Mock<HttpClient> GetMockObject(this HttpClient httpClient)
        {
            dynamic client = httpClient;
            var mock = (Mock<HttpClient>)client.Mock;
            return mock;
        }

        public static HttpClient CreateHttpClient(Dictionary<string, string> maps = null)
        {
            return CreateMockOfHttpClient(maps).Object;
        }

        public static Mock<HttpClient> CreateMockOfHttpClient(Dictionary<string, string> maps = null)
        {
            var defMap = new Dictionary<string, string>().MergesWith(maps);
            var mock = new Mock<HttpClient>();
            mock.Setup(
                f =>
                f.Post(It.IsAny<string>(),
                       It.IsAny<string>(),
                       It.IsAny<Action<HttpWebRequest>>())
                ).Returns((string url, string post, Action<HttpWebRequest> r) => {SetupMock(mock,url); return GetValue(defMap, url);});

            mock.Setup(
                f =>
                f.Post(It.IsAny<string>(),
                       It.IsAny<IEnumerable<KeyValuePair<string, string>>>(),
                       It.IsAny<Action<HttpWebRequest>>())
                ).Returns((string url, IEnumerable<KeyValuePair<string, string>> post, Action<HttpWebRequest> r) => {SetupMock(mock,url); return GetValue(defMap, url);});

            mock.Setup(
                f =>
                f.Post(It.IsAny<string>(),
                       It.IsAny<object>(),
                       It.IsAny<Action<HttpWebRequest>>())
                ).Returns((string url, object post, Action<HttpWebRequest> r) => {SetupMock(mock,url); return GetValue(defMap, url);});

            mock.Setup(f => f.Get(It.IsAny<string>(), It.IsAny<Action<HttpWebRequest>>()))
                .Returns((string url) => {SetupMock(mock,url); return GetValue(defMap, url);});

            

            return mock;
        }

        private static void SetupMock(Mock<HttpClient> mock,string url)
        {
            mock.Setup(f => f.Response).Returns(() =>
            {
                var mockResponse = new Mock<HttpWebResponse>();
                mockResponse.Setup(f => f.Headers)
                    .Returns(() =>
                    {
                        var headers = new WebHeaderCollection();
                        headers.Add("Date", DateTime.Now.ToUniversalTime().ToString());//"yyyy-MM-dd HH:mm:ss \"GMT\"zzz"
                        return headers;
                    });
                return mockResponse.Object;
            });
            mock.Setup(f => f.ResponseUrl).Returns(url);
        }

        private static string GetValue(Dictionary<string, string> defMap, string url)
        {
            foreach (var map in defMap)
            {
                if (url.Contains(map.Key))
                {
                    return map.Value;
                }
            }
            throw new Exception("No entry matches with " + url);
            return String.Empty;
        }
        
        public static void EnsureDeveloperAttention()
        {
            if (Environment.GetEnvironmentVariable("NCrunch") == "1")
                throw new Exception("PLEASE DO NOT RUN THIS TEST IN NCRUNCH");
            /*
            if (!Debugger.IsAttached)
            {
                Debugger.Break();
            }*/
            Debugger.Break();
        }
    }
}
